//====================================================================================================================================
// ����������� ������/����� ��������

`timescale 1ns / 1ps

// >>>>>>
//
// OE = memInRam[0][8:0]
// IO0 = OE[0] ? memInRam[0][31:24] : 8'hZZ;
//
// IO1 = OE[1] ? memInRam[1][ 7:0 ] : 8'hZZ;
// IO2 = OE[2] ? memInRam[1][15:8 ] : 8'hZZ;
// IO3 = OE[3] ? memInRam[1][23:16] : 8'hZZ;
// IO4 = OE[4] ? memInRam[1][31:24] : 8'hZZ;
//
// IO5 = OE[5] ? memInRam[2][ 7:0 ] : 8'hZZ;
// IO6 = OE[6] ? memInRam[2][15:8 ] : 8'hZZ;
// IO7 = OE[7] ? memInRam[2][23:16] : 8'hZZ;
// IO8 = OE[8] ? memInRam[2][31:24] : 8'hZZ;
//
// <<<<<<
//
// memOutRam[0][ 8:0 ] = OE;
// memOutRam[0][31:24] = IO0;
//
// memOutRam[1][ 7:0 ] = IO1;
// memOutRam[1][15:8 ] = IO2;
// memOutRam[1][23:16] = IO3;
// memOutRam[1][31:24] = IO4;
//
// memOutRam[2][ 7:0 ] = IO5;
// memOutRam[2][15:8 ] = IO6;
// memOutRam[2][23:16] = IO7;
// memOutRam[2][31:24] = IO8;
//
//====================================================================================================================================


module main(
	CLK50, IO0, IO1, IO2, IO4, OE,
	PCI_CLK, PCI_RSTn, PCI_AD, PCI_CBEn, PCI_PAR, PCI_FRAMEn, PCI_IRDYn, PCI_TRDYn, PCI_STOPn, PCI_IDSEL, PCI_DEVSELn, PCI_INTAn
);


//====================================================================================================================================


// main signals
input  CLK50;
inout  [7:0] IO0, IO1, IO2, IO4;
output [8:0] OE;

// PCI bus signals
input  PCI_CLK;
input  PCI_RSTn;
inout  [31:0] PCI_AD;
input  [3:0] PCI_CBEn;
inout  PCI_PAR;
input  PCI_FRAMEn;
input  PCI_IRDYn;
output PCI_TRDYn;
output PCI_STOPn;
input  PCI_IDSEL;
output PCI_DEVSELn;
output PCI_INTAn;


//====================================================================================================================================

parameter DEVICE_ID = 16'hC005;					// device 0xC005 (serial port 128+8bit)
parameter VENDOR_ID = 16'h4C53;					// `LS` (without PCI SIG allowing!)
parameter DEVICE_CLASS = 24'h078000;			// 088000 - Other system peripheral (see p. 262 of `PCI_Spec_v.2.2`)
parameter DEVICE_REV = 8'h01;						// device rev. #1

//====================================================================================================================================

wire [159:0] memOut;		// ������ "������" (��� ����������� �����������, ��������, ��������� ������ ��� FRAMEn==HIGH)
wire [159:0] memIn;		// ������ "�����"
wire cmdFlag;				// ������� ���������� ������ "�����"
wire [2:0] addrRcvd;		// �����, �� �������� ����� ������ PCI

frPciTarget #(DEVICE_ID, VENDOR_ID, DEVICE_CLASS, DEVICE_REV) pciTarget
	(memOut, memIn, cmdFlag, addrRcvd,
	PCI_CLK, PCI_RSTn, PCI_AD, PCI_CBEn, PCI_PAR, PCI_FRAMEn, PCI_IRDYn, PCI_TRDYn, PCI_STOPn, PCI_IDSEL, PCI_DEVSELn, PCI_INTAn);
//====================================================================================================================================

wire [31:0]memOutRam[4:0];
assign memOut[31 :0  ] = memOutRam[0];
assign memOut[63 :32 ] = memOutRam[1];
assign memOut[95 :64 ] = memOutRam[2];
assign memOut[127:96 ] = memOutRam[3];
assign memOut[159:128] = memOutRam[4];

//

wire [31:0]memInRam[4:0];
assign memInRam[0] = memIn[31 :0  ];
assign memInRam[1] = memIn[63 :32 ];
assign memInRam[2] = memIn[95 :64 ];
assign memInRam[3] = memIn[127:96 ];
assign memInRam[4] = memIn[159:128];

//assign OE = memInRam[4][7:0];

//assign IO0 = 8'hZZ;

  
wire S_clk_in   = IO1[0]; 
wire S_data_in  = IO1[2];
   
wire S_clk_out ;
wire S_data_out;

wire DIR_CLK   ;
wire DIR_DATA  ;
wire DIR_REMOTE; 
 


wire[31:0]data_in [3:0];
wire[31:0]data_out[3:0];

wire[7:0]cmd_out;
wire[7:0]cmd_in;
wire[3:0]subscriber_addr;

wire link_ok;

assign OE[0]   = 1;
assign OE[1]   = 0;
assign OE[2]   = 1;
assign OE[3]   = 0;
assign OE[4]   = 1; 
assign OE[8:5] = 0; 

assign IO0[2] = OE[0] ? S_clk_out  : 1'hZ;
assign IO0[4] = OE[0] ? S_data_out : 1'hZ;
assign IO0[0] = OE[0] ? 1'b1       : 1'hZ;
assign IO0[3] = OE[0] ? DIR_DATA   : 1'hZ;
assign IO0[1] = OE[0] ? DIR_REMOTE : 1'hZ;

assign IO2[0] = OE[2] ?  1 : 1'hZ;
assign IO2[1] = OE[2] ?  1 : 1'hZ;
assign IO2[2] = OE[2] ?  1 : 1'hZ;
assign IO2[3] = OE[2] ?  1 : 1'hZ;
assign IO2[4] = OE[2] ?  1 : 1'hZ;
assign IO2[5] = OE[2] ?  1 : 1'hZ;
assign IO2[6] = OE[2] ?  1 : 1'hZ;
assign IO2[7] = OE[2] ?  1 : 1'hZ;

assign IO4[7] = OE[4] ? link_ok : 1'hZ;

  
assign data_out[0] = memInRam[0];
assign data_out[1] = memInRam[1];
assign data_out[2] = memInRam[2];
assign data_out[3] = memInRam[3];

assign cmd_out         = memInRam[4][31:24];
assign subscriber_addr = memInRam[4][23:20];

assign memOutRam[0] = data_in[0];
assign memOutRam[1] = data_in[1];
assign memOutRam[2] = data_in[2];
assign memOutRam[3] = data_in[3];
assign memOutRam[4][31:24] = cmd_in[7:0];

reg subClk;
always@(posedge CLK50)subClk = ~subClk;

A_sp128_master #(8'd100) sp(CLK50,
							link_ok,
							DIR_DATA,
							DIR_REMOTE,
							subscriber_addr,
							S_clk_out,
							S_data_in, S_data_out, 
							data_in [0], data_in [1], data_in [2], data_in [3], cmd_in,
							data_out[0], data_out[1], data_out[2], data_out[3], cmd_out     
							);

endmodule
